#!/bin/sh
#
# BSD Router Project:	ucarp Init script with multiple VHID and FIB support
# http://bsdrp.net
#
# Based on the FreeBSD ucarp script from Nico <nico@rottenbytes.info>
#
# Copyright (c) 2010, The BSDRP Development Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE PROJECT ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# PROVIDE: ucarp
# REQUIRE: DAEMON
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf to enable & configure ucarp:
#
# ucarp_enable (bool):		Set it to "YES" to enable ucarp
#		Default is "NO".
# For all others variable, VHID is the Virtual IP identifier number (1-255)
# ucarp_VHID_if:			Set interface to use for ucarp checks
#		Default is "eth0"
# ucarp_VHID_src:			Set source (real) IP address of that host
# ucarp_VHID_pass:			Set password
#		Default is "dumbp4ss"
# ucarp_VHID_preempt (bool):		Set it to "YES" to become a master as soon as possible
#		Default is "NO"
# ucarp_VHID_addr:			Set virtual shared IP address
# ucarp_VHID_advbase:		Set advertisement frequency (seconds)
# ucarp_VHID_advskew:		Set advertisement skew (0-255)
# ucarp_VHID_upscript:		Run <file> to become a master
#		Default is "vip-up.sh"
# ucarp_VHID_downscript:		Run <file> to become a backup
#		Default is "vip-down.sh"
# ucarp_VHID_deadratio:		Set ratio to consider a host as dead
# ucarp_VHID_shutdown (bool):	Set it to "YES"  to call shutdown script at exit
#		Default is "YES"
# ucarp_VHID_facility:		Set syslog facility
#		Default is "daemon"
# ucarp_VHID_broadcast (bool):   Set it to "YES" to use Broadcast in place of multicast
#       Default is "NO"
# ucarp_VHID_fib:    		The alternative routing table id that ucarp should use
#       Default is "NONE"
# ucarp_VHID_xparam:		Send extra parameters to the vip-up/down script
#		ucarp send allready the $ucarp_VHID_if as $1 and $ucarp_VHID_addr as $2
#		this extra parameters is to be used as $3 in the vip-up/down.sh script
# ucarp_VHID_ignoreifstate (bool): Set to ignore the physical state of interface
#		Default is "NO"
# ucarp_VHID_neutral (bool): don't run downscript at start if backup
#		Default is "NO"

. /etc/rc.subr

ucarp_enable=${ucarp_enable-"NO"}

name="ucarp"
rcvar=${name}_enable
command="/usr/local/sbin/$name"

load_rc_config $name

start_cmd="${name}_start"

ucarp_start ()
{

for i in `jot - 1 255`; do
	# Now we need to use a variable-variable name :-(
	# eval will help us, but all:
	# -  non-variable-variable name
	# - " 
	# must be escaped with \

	eval "
		if ! [ -z \$ucarp_${i}_if ]; then
			# override these variables in /etc/rc.conf
			ucarp_${i}_pass=\${ucarp_${i}_pass:-\"dumbp4ss\"}
			ucarp_${i}_preempt=\${ucarp_${i}_preempt:-\"NO\"}
			ucarp_${i}_upscript=\${ucarp_${i}_upscript:-\"/usr/local/sbin/ucarp-up\"}
			ucarp_${i}_downscript=\${ucarp_${i}_downscript:-\"/usr/local/sbin/ucarp-down\"}
           	ucarp_${i}_shutdown=\${ucarp_${i}_shutdown:-\"YES\"}
           	ucarp_${i}_facility=\${ucarp_${i}_facility:-\"daemon\"}
            ucarp_${i}_broadcast=\${ucarp_${i}_broadcast:-\"NO\"}
			ucarp_${i}_fib=\${ucarp_${i}_fib:-\"NONE\"}
			ucarp_${i}_ignoreifstate=\${ucarp_${i}_ignoreifstate:-\"NO\"}
			ucarp_${i}_neutral=\${ucarp_${i}_neutral:-\"NO\"}

    		if [ \"\${ucarp_${i}_fib}\" != \"NONE\" ]; then
				if ! [ `sysctl net.fibs >/dev/null 2>&1` ]; then
        			command=\"setfib -F \${ucarp_${i}_fib} /usr/local/sbin/$name\"
    			else
					echo \"FIB configured for VHID $i but FIB not enabled ! please enable it\"
                	exit 1
    			fi
			fi
			
			command_args=\"-i \$ucarp_${i}_if -v $i -p \$ucarp_${i}_pass -f \$ucarp_${i}_facility -B \"

			if [ \$ucarp_${i}_preempt = \"YES\" ]; then
        		command_args=\${command_args}\"-P \"
    		fi

			if [ \$ucarp_${i}_shutdown = \"YES\" ]; then
           		command_args=\${command_args}\"-z \"
           	fi

			if [ \$ucarp_${i}_broadcast = \"YES\" ]; then
                command_args=\${command_args}\"-M \"
            fi

			# Mandatory arguments
    		if [ -z \$ucarp_${i}_src ]; then
        		echo \"source address is not set for VHID $i ! please set it\"
        		exit 1
    		fi

    		if [ -z \$ucarp_${i}_addr ]; then
        		echo \"virtual address is not set for VHID $i ! please set it\"
        		exit 1
    		fi
	
			command_args=\${command_args}\"-s \$ucarp_${i}_src -a \$ucarp_${i}_addr \"
	
			# Optional args
			if ! [ -z \$ucarp_${i}_upscript ]; then
				command_args=\${command_args}\"-u \$ucarp_${i}_upscript \"
			fi
			if ! [ -z \$ucarp_${i}_downscript ]; then
				command_args=\${command_args}\"-d \$ucarp_${i}_downscript \"
			fi
			if ! [ -z \$ucarp_${i}_deadratio ]; then
				command_args=\${command_args}\"-r \$ucarp_${i}_deadratio \"
			fi
			if ! [ -z \$ucarp_${i}_advbase ]; then
				command_args=\${command_args}\"-b \$ucarp_${i}_advbase \"
			fi
			if ! [ -z \$ucarp_${i}_advskew ]; then
				command_args=\${command_args}\"-k \$ucarp_${i}_advskew \"
			fi
			if ! [ -z \$ucarp_${i}_xparam ]; then	
				command_args=\${command_args}\"-x \$ucarp_${i}_xparam \"
			fi
			if [ \$ucarp_${i}_ignoreifstate = \"YES\" ]; then
                command_args=\${command_args}\"-S \"
            fi
			if [ \$ucarp_${i}_neutral = \"YES\" ]; then
                command_args=\${command_args}\"-n \"
            fi
	
			\$command \$command_args
		fi
	"
done
}

run_rc_command "$1"
